package com.campus.service.impl;

import com.campus.common.RedisCache;
import com.campus.common.Result;
import com.campus.entity.HotRankings;
import com.campus.entity.PostViews;
import com.campus.mapper.HotRankingsMapper;
import com.campus.mapper.PostViewsMapper;
import com.campus.mapper.PostsMapper;
import com.campus.service.HotRankingService;
import com.campus.service.PostViewService;
import com.campus.utils.AllUtils;
import com.campus.utils.SnowFlakeUtil;
import com.campus.service.impl.HotRankingServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Service
public class PostViewServiceImpl implements PostViewService {

    @Autowired
    private PostViewsMapper postViewsMapper;

    @Autowired
    private PostsMapper postsMapper;
    @Autowired
    private HotRankingsMapper hotRankingsMapper;
    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private HotRankingService hotRankingService;

    @Override
    public Result recordPostView(String postId, String userId) {
        try {
            // 检查用户是否已经浏览过该帖子
            int viewExists = postViewsMapper.checkViewExists(postId, userId);

            // 如果用户还没有浏览过该帖子，则记录浏览并更新浏览量
            if (viewExists == 0) {
                // 插入浏览记录
                PostViews postViews = new PostViews(
                        SnowFlakeUtil.getId().toString(),
                        postId,
                        userId,
                        new Date()
                );
                postViewsMapper.insertPostView(postViews);

                // 更新帖子的浏览量
                postsMapper.updateViewsCount(postId);
            }

            // 获取并返回当前浏览量
            Integer viewCount = postViewsMapper.getViewCountByPostId(postId);
            if (viewCount == null) {
                viewCount = 0;
            }
            Set<String> categoryKeys = stringRedisTemplate.keys("category*");
            stringRedisTemplate.delete(categoryKeys);
            // 更新posts表中的浏览量
            postsMapper.updateViewsCount(postId);

//            Set<String> categoryKeys = stringRedisTemplate.keys("category*");
            stringRedisTemplate.delete(categoryKeys);
            //这里点赞成功之后先在热力表里面查询有就把总数更新，没有的话就默认为1
            HotRankings hotRanking = hotRankingsMapper.getHotRankingsByPostId(postId);
            if (hotRanking == null) {
                //获取分类id
                String categoryId = postsMapper.getCategoryIdByPostId(postId);
                //如果为null那么就插入
                HotRankings hotRankings = new HotRankings();
                hotRankings.setRankingId(SnowFlakeUtil.getId().toString());
                hotRankings.setPostId(postId);
                hotRankings.setCategoryId(categoryId);
                hotRankings.setViewsCount(viewCount);
                // 确保likesCount不为null
                if (hotRankings.getLikesCount() == null) {
                    hotRankings.setLikesCount(0);
                }
                hotRankings.setHotScore(hotRankings.getLikesCount() * 3 + hotRankings.getViewsCount() * 2);
                int i1 = hotRankingsMapper.insertHotRankingsByViewCount(hotRankings);
                // 同时更新posts表中的热力值
                postsMapper.updateHotScore(postId, hotRankings.getHotScore());
            } else {
                //这里代表数据库中有数据那么就更新点赞以及分数
                int score = hotRanking.getHotScore() + 2;
                hotRanking.setHotScore(score);
                hotRanking.setViewsCount(viewCount);
                int i1 = hotRankingsMapper.updateHotRankingsViewCountByPostId(hotRanking, postId);
                // 同时更新posts表中的热力值
                postsMapper.updateHotScore(postId, hotRanking.getHotScore());
            }

            // 更新Redis ZSet中的分数
            updateHotRankingZSet(postId, hotRanking != null ? hotRanking.getLikesCount() : 0, viewCount,
                    hotRanking != null ? hotRanking.getCommentsCount() : 0);
            //这个是获取今日的帖子浏览量
            String dayNumRedis = stringRedisTemplate.opsForValue().get(RedisCache.TODAY_POST_VIEW_COUNT);
            int dayNum = dayNumRedis == null ? 1 : Integer.valueOf(dayNumRedis) + 1;
            stringRedisTemplate.opsForValue().set(RedisCache.TODAY_POST_VIEW_COUNT, dayNum + "");
            //这个是获取本周的帖子浏览量
            String weekNumRedis = stringRedisTemplate.opsForValue().get(RedisCache.WEEK_POST_VIEW_COUNT);
            int weekNum = weekNumRedis == null ? 1 : Integer.valueOf(weekNumRedis) + 1;
            stringRedisTemplate.opsForValue().set(RedisCache.WEEK_POST_VIEW_COUNT, weekNum + "");
            //这个是获取本月的帖子浏览量
            String monthNumRedis = stringRedisTemplate.opsForValue().get(RedisCache.MONTH_POST_VIEW_COUNT);
            int monthNum = monthNumRedis == null ? 1 : Integer.valueOf(monthNumRedis) + 1;
            stringRedisTemplate.opsForValue().set(RedisCache.MONTH_POST_VIEW_COUNT, monthNum + "");
            //给这个键设置过期时间
            stringRedisTemplate.expire(RedisCache.TODAY_POST_VIEW_COUNT,AllUtils.getHoursToMidnightCeil(),TimeUnit.HOURS);
            stringRedisTemplate.expire(RedisCache.WEEK_POST_VIEW_COUNT,AllUtils.getHoursToEndOfWeekCeil(),TimeUnit.HOURS);
            stringRedisTemplate.expire(RedisCache.MONTH_POST_VIEW_COUNT,AllUtils.getHoursToEndOfMonthCeil(),TimeUnit.HOURS);
            return Result.ok("浏览记录成功", viewCount);
        } catch (Exception e) {
            return Result.err(Result.CODE_500, "浏览记录失败: " + e.getMessage());
        }
    }

    @Override
    public Result getViewCount(String postId) {
        try {
            Integer viewCount = postViewsMapper.getViewCountByPostId(postId);
            if (viewCount == null) {
                viewCount = 0;
            }
            return Result.ok(viewCount);
        } catch (Exception e) {
            return Result.err(Result.CODE_500, "获取浏览量失败: " + e.getMessage());
        }
    }

    /**
     * 更新热力榜ZSet中的分数
     *
     * @param postId        帖子ID
     * @param likesCount    点赞数
     * @param viewsCount    浏览量
     * @param commentsCount 评论数
     */
    private void updateHotRankingZSet(String postId, int likesCount, int viewsCount, int commentsCount) {
        // 更新今天、本周、本月的热力榜
        ((HotRankingServiceImpl) hotRankingService).updatePostScoreInZSet(postId, likesCount, viewsCount, commentsCount, "today");
        ((HotRankingServiceImpl) hotRankingService).updatePostScoreInZSet(postId, likesCount, viewsCount, commentsCount, "week");
        ((HotRankingServiceImpl) hotRankingService).updatePostScoreInZSet(postId, likesCount, viewsCount, commentsCount, "month");
    }
}